package com.xxx.yuedong.mall.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.zxing.WriterException;
import com.xxx.yuedong.common.exception.YuedongException;
import com.xxx.yuedong.mall.common.Constant;
import com.xxx.yuedong.mall.controller.form.DirCreateOrderForm;
import com.xxx.yuedong.mall.exception.MallException;
import com.xxx.yuedong.mall.exception.MallExceptionEnum;
import com.xxx.yuedong.mall.model.dao.CartMapper;
import com.xxx.yuedong.mall.model.dao.OrderItemMapper;
import com.xxx.yuedong.mall.model.dao.OrderMapper;
import com.xxx.yuedong.mall.model.dao.ProductMapper;
import com.xxx.yuedong.mall.model.pojo.Order;
import com.xxx.yuedong.mall.model.pojo.OrderItem;
import com.xxx.yuedong.mall.model.pojo.Product;
import com.xxx.yuedong.mall.controller.form.CreateOrderForm;
import com.xxx.yuedong.mall.model.vo.CartVO;
import com.xxx.yuedong.mall.model.vo.OrderItemVO;
import com.xxx.yuedong.mall.model.vo.OrderVO;
import com.xxx.yuedong.mall.quartz.CancelOrderJob;
import com.xxx.yuedong.mall.service.CartService;
import com.xxx.yuedong.mall.service.OrderService;
import com.xxx.yuedong.mall.util.OrderCodeFactory;
import com.xxx.yuedong.mall.util.QRCodeGenerator;
import com.xxx.yuedong.mall.util.QuartzUtil;
import com.xxx.yuedong.mine.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * 描述：     订单Service实现类
 * @author hc
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    CartService cartService;

    @Autowired
    ProductMapper productMapper;

    @Autowired
    CartMapper cartMapper;

    @Resource(name = "mall-order")
    OrderMapper orderMapper;

    @Autowired
    OrderItemMapper orderItemMapper;


    @Autowired
    UserService userService;

    @Autowired
    QuartzUtil quartzUtil;

    @Value("${alipay.notifyUrl}")
    private String notifyUrl;

    @Autowired
    private AlipayClient alipayClient;

    public String createAlipayAmectPayOrder(HashMap param) {
        String orderNo = MapUtil.getStr(param,"orderNo");
        String orderStatus = MapUtil.getStr(param,"orderStatus");
        // 根据罚款单 id 和用户 id 查找对应的罚款信息
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order != null) {
            // 获取到订单金额
            BigDecimal totalPrice = new BigDecimal(order.getTotalPrice()).divide(new BigDecimal(100));
            BigDecimal roundedPrice = totalPrice.setScale(2, BigDecimal.ROUND_HALF_UP);
            System.out.println(roundedPrice.toString());
            try {
                AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
                JSONObject json = new JSONObject();
                param.clear();
                json.set("out_trade_no",order.getOrderNo());
                json.set("subject","购买商品");
                json.set("total_amount",roundedPrice.toString());
                request.setBizContent(json.toString());
                request.setNotifyUrl(notifyUrl);
                // 执行请求，拿到响应
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                if (response.isSuccess()){
                    System.out.println(response.getBody());
//                    AlipayTradeQueryRequest req = new AlipayTradeQueryRequest();
//                    req.setBizContent(json.toString());
//                    AlipayTradeQueryResponse resp = alipayClient.execute(req);
//                    String outTradeNo = resp.getOutTradeNo();
//                    System.out.println(outTradeNo);
                    param.clear();
                    HashMap map = new HashMap() {{
                        put("orderNo", order.getOrderNo());
                        //设置状态10,表示订单创建成功，但并未付款
                        put("orderStatus", Constant.OrderStatusEnum.NOT_PAID.getCode());
                    }};
                    int rows = orderMapper.updateOrderStatus(map);
                    // 将二维码图片编译成 base64 编码的字符串返回到前端生成二维码图片
//                    QrConfig qrConfig = new QrConfig();
//                    qrConfig.setWidth(255);
//                    qrConfig.setHeight(255);
//                    qrConfig.setMargin(2);
//                    String qrCodeBase64 = QrCodeUtil.generateAsBase64(response.getQrCode(), qrConfig, "jpg");

                    return response.getBody();
                } else {
                    log.error("订单不存在");
                    throw new MallException(MallExceptionEnum.NO_ORDER);
                }
            } catch (Exception e) {
                log.error("创建支付订单失败",e);
                throw new MallException(20001,"创建支付订单失败");
            }
        } else {
            log.error("订单不存在");
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
    }

    //数据库事务
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String create(CreateOrderForm createOrderReq) {

        //拿到用户ID
        Integer userId = StpUtil.getLoginIdAsInt();

        //从购物车查找已经勾选的商品
        List<CartVO> cartVOList = cartService.list(userId);
        ArrayList<CartVO> cartVOListTemp = new ArrayList<>();
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            if (cartVO.getSelected().equals(Constant.Cart.SELECTED)) {
                cartVOListTemp.add(cartVO);
            }
        }
        cartVOList = cartVOListTemp;
        //如果购物车已勾选的为空，报错
        if (CollectionUtils.isEmpty(cartVOList)) {
            throw new MallException(MallExceptionEnum.CART_EMPTY);
        }
        //判断商品是否存在、上下架状态、库存
        validSaleStatusAndStock(cartVOList);
        //把购物车对象转为订单item对象
        List<OrderItem> orderItemList = cartVOListToOrderItemList(cartVOList);
        //扣库存
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
            int stock = product.getStock() - orderItem.getQuantity();
            if (stock < 0) {
                throw new MallException(MallExceptionEnum.NOT_ENOUGH);
            }
            product.setStock(stock);
            productMapper.updateByPrimaryKeySelective(product);
        }
        //把购物车中的已勾选商品删除
        cleanCart(cartVOList);
        //生成订单
        Order order = new Order();
        //生成订单号，有独立的规则
        String orderNo = OrderCodeFactory.getOrderCode(Long.valueOf(userId));
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setTotalPrice(totalPrice(orderItemList));
        order.setReceiverName(createOrderReq.getReceiverName());
        order.setReceiverMobile(createOrderReq.getReceiverMobile());
        order.setReceiverAddress(createOrderReq.getReceiverAddress());
//        order.setOrderStatus(Constant.OrderStatusEnum.NOT_PAID.getCode());
        order.setPostage(0);
        order.setPaymentType(1);
        //插入到Order表
        orderMapper.insertSelective(order);

        //循环保存每个商品到order_item表
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            orderItem.setOrderNo(order.getOrderNo());
            orderItemMapper.insertSelective(orderItem);
        }

        // 创建会议工作流任务组
        JobDetail jobDetail = JobBuilder.newJob(CancelOrderJob.class).build();
        Map dataMap = jobDetail.getJobDataMap();
        dataMap.put("orderNo",orderNo);
        Date executeDate = DateUtil.date(order.getCreateTime()).offset(DateField.MINUTE,5);
        quartzUtil.addJob(jobDetail,"cancelOrderJob_" + orderNo,"订单流组",executeDate);

        HashMap param = new HashMap();
        param.put("orderNo",orderNo);
        String qrCode = createAlipayAmectPayOrder(param);
        //把结果返回
        return qrCode;
    }

    @Transactional(rollbackFor = Exception.class)
    public String directCreateOrder(DirCreateOrderForm form) {

        // 拿到用户ID
        Integer userId = StpUtil.getLoginIdAsInt();

        // 获取商品ID和数量
        Integer productId = form.getProductId();
        Integer quantity = form.getQuantity();

        // 通过构造 CartVO 对象构建一个 List
        List<CartVO> cartVOList = new ArrayList<>();
        CartVO cartVO = new CartVO();
        cartVO.setProductId(productId);
        cartVO.setQuantity(quantity);
        cartVOList.add(cartVO);

        // 判断商品是否存在、上下架状态、库存
        validSaleStatusAndStock(cartVOList);

        // 扣除库存
        Product product = productMapper.selectByPrimaryKey(productId);
        int stock = product.getStock() - quantity;
        if (stock < 0) {
            throw new MallException(MallExceptionEnum.NOT_ENOUGH);
        }
        product.setStock(stock);
        productMapper.updateByPrimaryKeySelective(product);

        // 生成订单
        Order order = new Order();
        String orderNo = OrderCodeFactory.getOrderCode(Long.valueOf(userId));
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setTotalPrice(product.getPrice() * quantity);
        order.setReceiverName(form.getReceiverName());
        order.setReceiverMobile(form.getReceiverMobile());
        order.setReceiverAddress(form.getReceiverAddress());
//        order.setOrderStatus(Constant.OrderStatusEnum.NOT_PAID.getCode());
        order.setPostage(0);
        order.setPaymentType(1);
        orderMapper.insertSelective(order);

        // 保存订单项到order_item表
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderNo(order.getOrderNo());
        orderItem.setProductId(productId);
        orderItem.setProductName(product.getName());
        orderItem.setProductImg(product.getImage());
        orderItem.setUnitPrice(product.getPrice());
        orderItem.setQuantity(quantity);
        orderItem.setTotalPrice(product.getPrice() * quantity);
        orderItemMapper.insertSelective(orderItem);

        // 创建会议工作流任务组
        JobDetail jobDetail = JobBuilder.newJob(CancelOrderJob.class).build();
        Map dataMap = jobDetail.getJobDataMap();
        dataMap.put("orderNo",orderNo);
        Date executeDate = DateUtil.date(order.getCreateTime()).offset(DateField.MINUTE,5);
        quartzUtil.addJob(jobDetail,"cancelOrderJob_" + orderNo,"订单流组",executeDate);

        // 返回订单号
//        return orderNo;
        HashMap param = new HashMap();
        param.put("orderNo",orderNo);
        String qrCode = createAlipayAmectPayOrder(param);
        //把结果返回
        return qrCode;
    }

    private Integer totalPrice(List<OrderItem> orderItemList) {
        Integer totalPrice = 0;
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            totalPrice += orderItem.getTotalPrice();
        }
        return totalPrice;
    }

    private void cleanCart(List<CartVO> cartVOList) {
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            cartMapper.deleteByPrimaryKey(cartVO.getId());
        }
    }

    private List<OrderItem> cartVOListToOrderItemList(List<CartVO> cartVOList) {
        List<OrderItem> orderItemList = new ArrayList<>();
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(cartVO.getProductId());
            //记录商品快照信息
            orderItem.setProductName(cartVO.getProductName());
            orderItem.setProductImg(cartVO.getProductImage());
            orderItem.setUnitPrice(cartVO.getPrice());
            orderItem.setQuantity(cartVO.getQuantity());
            orderItem.setTotalPrice(cartVO.getTotalPrice());
            orderItemList.add(orderItem);
        }
        return orderItemList;
    }

    private void validSaleStatusAndStock(List<CartVO> cartVOList) {
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            Product product = productMapper.selectByPrimaryKey(cartVO.getProductId());
            //判断商品是否存在，商品是否上架
            if (product == null || product.getStatus().equals(Constant.SaleStatus.NOT_SALE)) {
                throw new MallException(MallExceptionEnum.NOT_SALE);
            }
            //判断商品库存
            if (cartVO.getQuantity() > product.getStock()) {
                throw new MallException(MallExceptionEnum.NOT_ENOUGH);
            }
        }
    }

    @Override
    public OrderVO detail(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        //订单不存在，则报错
        if (order == null) {
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        //订单存在，需要判断所属
        Integer userId = StpUtil.getLoginIdAsInt();
        if (!order.getUserId().equals(userId)) {
            throw new MallException(MallExceptionEnum.NOT_YOUR_ORDER);
        }
        OrderVO orderVO = getOrderVO(order);
        return orderVO;
    }

    private OrderVO getOrderVO(Order order) {
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        //获取订单对应的orderItemVOList
        List<OrderItem> orderItemList = orderItemMapper.selectByOrderNo(order.getOrderNo());
        List<OrderItemVO> orderItemVOList = new ArrayList<>();
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            OrderItemVO orderItemVO = new OrderItemVO();
            BeanUtils.copyProperties(orderItem, orderItemVO);
            orderItemVOList.add(orderItemVO);
        }
        orderVO.setOrderItemVOList(orderItemVOList);
        orderVO.setOrderStatusName(Constant.OrderStatusEnum.codeOf(orderVO.getOrderStatus()).getValue());
        return orderVO;
    }

    @Override
    public PageInfo listForCustomer(Integer pageNum, Integer pageSize) {
        Integer userId = StpUtil.getLoginIdAsInt();
        PageHelper.startPage(pageNum, pageSize);
        List<Order> orderList = orderMapper.selectForCustomer(userId);
        List<OrderVO> orderVOList = orderListToOrderVOList(orderList);
        PageInfo pageInfo = new PageInfo<>(orderList);
        pageInfo.setList(orderVOList);
        return pageInfo;
    }

    private List<OrderVO> orderListToOrderVOList(List<Order> orderList) {
        List<OrderVO> orderVOList = new ArrayList<>();
        for (int i = 0; i < orderList.size(); i++) {
            Order order = orderList.get(i);
            OrderVO orderVO = getOrderVO(order);
            orderVOList.add(orderVO);
        }
        return orderVOList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        //查不到订单，报错
        if (order == null) {
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        //验证用户身份
        //订单存在，需要判断所属
        HashMap map = orderMapper.searchReceiver(Long.valueOf(orderNo));
        Integer userId = (Integer) map.get("userId");
        if (!order.getUserId().equals(userId)) {
            throw new MallException(MallExceptionEnum.NOT_YOUR_ORDER);
        }
        if (order.getOrderStatus().equals(Constant.OrderStatusEnum.NOT_PAID.getCode())) {
            // 获取订单的商品信息
            List<OrderItem> orderItems = orderItemMapper.selectByOrderNo(orderNo);
            order.setOrderStatus(Constant.OrderStatusEnum.CANCELED.getCode());
            order.setEndTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
            // 恢复商品库存
            for (OrderItem orderItem : orderItems) {
                Integer productId = orderItem.getProductId();
                Integer quantity = orderItem.getQuantity();

                Product product = productMapper.selectByPrimaryKey(productId);
                int stock = product.getStock() + quantity;
                product.setStock(stock);
                productMapper.updateByPrimaryKeySelective(product);
            }
        } else {
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        }
        if(order.getOrderStatus() == 0){
            quartzUtil.deleteJob("cancelOrderJob_" + orderNo, "取消订单任务组");
        }
    }

//    @Override
//    public String qrcode(String orderNo) {
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
//                .getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
//
//        String address = ip + ":" + request.getLocalPort();
//        String payUrl = "http://" + address + "/pay?orderNo=" + orderNo;
//        try {
//            QRCodeGenerator
//                    .generateQRCodeImage(payUrl, 350, 350,
//                            Constant.FILE_UPLOAD_DIR + orderNo + ".png");
//        } catch (WriterException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        String pngAddress = "http://" + address + "/images/" + orderNo + ".png";
//        return pngAddress;
//    }

//    @Override
//    public void pay(String orderNo) {
//        Order order = orderMapper.selectByOrderNo(orderNo);
//        //查不到订单，报错
//        if (order == null) {
//            throw new MallException(MallExceptionEnum.NO_ORDER);
//        }
//        if (order.getOrderStatus() == Constant.OrderStatusEnum.NOT_PAID.getCode()) {
//            order.setOrderStatus(Constant.OrderStatusEnum.PAID.getCode());
//            order.setPayTime(new Date());
//            orderMapper.updateByPrimaryKeySelective(order);
//        } else {
//            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
//        }
//    }

    @Override
    public PageInfo listForAdmin(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Order> orderList = orderMapper.selectAllForAdmin();
        List<OrderVO> orderVOList = orderListToOrderVOList(orderList);
        PageInfo pageInfo = new PageInfo<>(orderList);
        pageInfo.setList(orderVOList);
        return pageInfo;
    }

    //发货
    @Override
    public void deliver(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        //查不到订单，报错
        if (order == null) {
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        if (order.getOrderStatus() == Constant.OrderStatusEnum.PAID.getCode()) {
            order.setOrderStatus(Constant.OrderStatusEnum.DELIVERED.getCode());
            order.setDeliveryTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
        } else {
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        }
    }

    @Override
    public void finish(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        //查不到订单，报错
        if (order == null) {
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        //如果是普通用户，就要校验订单的所属
//        if (!userService.checkAdminRole(UserFilter.currentUser) && !order.getUserId().equals(UserFilter.currentUser.getId())) {
//            throw new ImoocMallException(ImoocMallExceptionEnum.NOT_YOUR_ORDER);
//        }
        //发货后可以完结订单
        if (order.getOrderStatus() == Constant.OrderStatusEnum.DELIVERED.getCode()) {
            order.setOrderStatus(Constant.OrderStatusEnum.FINISHED.getCode());
            order.setEndTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
        } else {
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        }
    }

    @Override
    public HashMap searchReceiver(Long orderNo) {
        HashMap map = orderMapper.searchReceiver(orderNo);
        return map;
    }

    @Override
    public int updateOrderStatus(HashMap param) {
        int rows = orderMapper.updateOrderStatus(param);
        return rows;
    }
}
